using System;
using UnityEngine;

namespace Super
{
	public class ColorEraserBrush : MonoBehaviour
	{
		public enum WorkType
		{
			Brush,
			Eraser,
		}

		public bool isEnable;
		public WorkType workType;
		public bool isWorking;
		public Color color;
		[Range(0.005f, 0.2f)]
		public float size;
		[Range(0.001f, 0.005f)]
		public float smoothness;
		public GameObject broad;
		public string mainTexName = "";

		Material brushMaterial;
		Material eraserMaterial;
		Material broadMaterial;
		RenderTexture afterBrushTex;
		RenderTexture beforeBrushTex;
		Vector2 lastUv;

        void Awake()
		{
			mainTexName = string.IsNullOrEmpty(mainTexName) ? "_BaseMap" : mainTexName;
			broadMaterial = broad.GetComponent<MeshRenderer>().material;
			Texture curTex = broadMaterial.GetTexture(mainTexName) ?? GlobalUtil.GetTexture2D(Color.white, 1920, 1080);

			brushMaterial = new Material(Shader.Find("FormeWork/Brush"));
			eraserMaterial = new Material(Shader.Find("FormeWork/Eraser"));

			afterBrushTex = new RenderTexture(curTex.width, curTex.height, 24, RenderTextureFormat.ARGB32);
			beforeBrushTex = new RenderTexture(curTex.width, curTex.height, 24, RenderTextureFormat.ARGB32);

			Graphics.Blit(curTex, beforeBrushTex);
			Texture2D sourceTex = GlobalUtil.RenderTextureToTexture2D(beforeBrushTex);
			eraserMaterial.SetTexture("_SourceTex", sourceTex);

			SetPaintBrush(color, size);
			SetEraser(size);
		}

		void Update()
		{
			if (isEnable)
			{
				Plane plane = new Plane(broad.transform.forward, broad.transform.position);
				transform.position = GlobalUtil.GetMouseInPlanePos(plane) - broad.transform.forward;
			}
		}

		#region 功能函数

		public void WorkWithColor(Vector2 uvPos)
		{
			Material material = workType == WorkType.Brush ? brushMaterial : eraserMaterial;
			material.SetVector("_BrushPos", new Vector4(uvPos.x, uvPos.y, 0, 0));
			material.SetFloat("_XYScaling", broad.transform.localScale.x / broad.transform.localScale.y);

			Graphics.Blit(beforeBrushTex, afterBrushTex, material);
			broadMaterial.SetTexture(mainTexName, afterBrushTex);
			Graphics.Blit(afterBrushTex, beforeBrushTex);
		}

		public void SetPaintBrush(Color color, float size)
		{
			if (brushMaterial == null) return;
			brushMaterial.SetColor("_BrushColor", color);
			brushMaterial.SetFloat("_BrushSize", size);
		}

		public void SetEraser(float size)
		{
			if (eraserMaterial == null) return;
			eraserMaterial.SetFloat("_BrushSize", size);
		}

        #endregion

        #region 系统事件

        public void OnValidate()
        {
            SetPaintBrush(color, size);
			SetEraser(size);
        }

        public void OnEnable()
		{
			EventManager.Register<MouseDragGE>(OnDrag);
			EventManager.Register<MouseUpGE>(OnUp);
		}

		public void OnDisable()
		{
			EventManager.UnRegisterAll(gameObject);
		}

		public void OnDrag(MouseDragGE mouseDragGE)
		{
			if (!isEnable || mouseDragGE.key != MouseKey.Left)
				return;
			Ray ray = new Ray(transform.position, -transform.up);
			if (Physics.Raycast(ray, out RaycastHit raycastHit, 5))
			{

				if (raycastHit.transform.gameObject != broad)
					return;

				if (isWorking)
				{
					Vector2 dir = raycastHit.textureCoord - lastUv;
					int fillNum = Mathf.CeilToInt(Vector2.Distance(raycastHit.textureCoord, lastUv) / smoothness);
					for (int i = 1; i < fillNum; i++)
					{
						WorkWithColor(lastUv + dir.normalized * i * smoothness);
					}
				}
				WorkWithColor(raycastHit.textureCoord);
				isWorking = true;
				lastUv = raycastHit.textureCoord;
			}
		}

		private void OnUp(MouseUpGE mouseUpGE)
		{
			if (!isEnable || mouseUpGE.key != MouseKey.Left)
				return;
			isWorking = false;
		}

		public void OnDrawGizmos()
		{
			Debug.DrawLine(transform.position, transform.position - transform.up * 10, Color.red, 3);
		}

		#endregion
	}

}

